package com.starblink.imgsearch.camera

import android.annotation.SuppressLint
import android.os.Build
import androidx.camera.core.AspectRatio
import androidx.camera.core.Camera
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageCapture
import androidx.camera.core.Preview
import androidx.camera.core.UseCaseGroup
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.content.ContextCompat
import com.starblink.basic.log.SKLogger
import com.starblink.basic.log.report.ErrorReporter
import com.starblink.imgsearch.camera.ui.CameraTVMActivity
import java.util.concurrent.ExecutionException
import java.util.concurrent.Executors

/**相机模式*/
enum class CameraMode() {
    QR_SCAN,
    CAMERA,
}

/**相机设置管理器*/
@SuppressLint("UnsafeOptInUsageError")
class CamConfig(private val mActivity: CameraTVMActivity) {

    companion object {
        const val TAG = "Camera-CamConfig"
        val DEFAULT_CAMERA_MODE = CameraMode.CAMERA
        const val DEFAULT_LENS_FACING = CameraSelector.LENS_FACING_BACK
    }

    var camera: Camera? = null

    /**
     * ProcessCameraProvider是一个单例 用于将相机的生命周期绑定到应用程序进程中的任何 生命周期持有者。
     * 因为cameraX具有生命周期感应 这可以使我们的应用程序省去打开和关闭相机的任务
     */
    var cameraProvider: ProcessCameraProvider? = null

    /**UseCase:拍照*/
    var imageCapture: ImageCapture? = null
        private set

    /**UseCase:预览*/
    private var preview: Preview? = null

    /**
     * 相机线程池
     * @note imageAnalyzer运行在该线程池中
     */
    val cameraExecutor by lazy {
        Executors.newSingleThreadExecutor()
    }

    /**UseCase:图片分析*/
    var imageAnalyzer: ImageAnalysis? = null
    private var qrAnalyzer: QRAnalyzer? = null

    /**是否是扫描二维码模式*/
    var isQRMode = false
        private set

    private var currentMode: CameraMode = DEFAULT_CAMERA_MODE

    /**相机拍照比例*/
    var aspectRatio: Int = AspectRatio.RATIO_4_3
        get() {
            return when {
                isQRMode -> {
                    AspectRatio.RATIO_4_3
                }

                else -> {
                    // 拍照模式
                    AspectRatio.RATIO_16_9
                }
            }
        }

    /**摄像头朝向：后置Or前置，默认后置*/
    var lensFacing = DEFAULT_LENS_FACING

    /**摄像头选择器*/
    private lateinit var cameraSelector: CameraSelector

    /**切换摄像头*/
    fun toggleCameraSelector() {
        lensFacing =
            if (lensFacing == CameraSelector.LENS_FACING_BACK)
                CameraSelector.LENS_FACING_FRONT
            else
                CameraSelector.LENS_FACING_BACK

        // 仅当手机支持该摄像头时，重启相机；否则，回退设置
        if (isLensFacingSupported(lensFacing)) {
            startCamera(true)
        } else {
            lensFacing = if (lensFacing == CameraSelector.LENS_FACING_BACK) {
                CameraSelector.LENS_FACING_FRONT
            } else {
                CameraSelector.LENS_FACING_BACK
            }
        }
    }

    /**初始化相机*/
    fun initializeCamera(forced: Boolean = false) {
        if (cameraProvider != null) {
            startCamera(forced = forced)
            return
        }

        val cameraProviderFuture = ProcessCameraProvider.getInstance(mActivity)

        // 初始化cameraProvider
        cameraProviderFuture.addListener(fun() {
            try {
                cameraProvider = cameraProviderFuture.get()
            } catch (e: ExecutionException) {
                SKLogger.i(
                    TAG,
                    "Failed to load camera provider due to OS or hardware issue. Try rebooting."
                )
                return
            }

            // 如果当前设备不支持当前朝向，修改为相反朝向
            if (!isLensFacingSupported(lensFacing)) {
                lensFacing = if (lensFacing == CameraSelector.LENS_FACING_BACK) {
                    CameraSelector.LENS_FACING_FRONT
                } else {
                    CameraSelector.LENS_FACING_BACK
                }
            }

            startCamera(forced = forced)
        }, ContextCompat.getMainExecutor(mActivity))
    }

    private fun isLensFacingSupported(lensFacing: Int): Boolean {
        val tCameraSelector = CameraSelector.Builder()
            .requireLensFacing(lensFacing)
            .build()

        return cameraProvider?.hasCamera(tCameraSelector) ?: false
    }


    /**
     * 根据最新的配置信息，启动相机
     * @param forced 是否强制启动相机
     */
    fun startCamera(forced: Boolean = false) {
        if ((!forced && camera != null) || cameraProvider == null) return

        // 测试哪种合适？
        val rotation = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            val display = mActivity.display
            display?.rotation ?: @Suppress("DEPRECATION")
            mActivity.windowManager.defaultDisplay.rotation
        } else {
            @Suppress("DEPRECATION")
            mActivity.windowManager.defaultDisplay.rotation
        }
//        private fun getRotation(): Int {
//            return if (viewBinding.viewFinder.display != null) viewBinding.viewFinder.display.rotation else android.view.Surface.ROTATION_0
//        }

        if (mActivity.isDestroyed || mActivity.isFinishing) return

        cameraSelector = CameraSelector.Builder()
            .requireLensFacing(lensFacing)
            .build()

        // 获取相机预览最后一帧，在相机从解绑到重新绑定期间，显示该帧毛玻璃效果图。（默认是黑屏效果）
        mActivity.updateLastFrame()

        // Unbind/close all other camera(s) [if any]
        cameraProvider?.unbindAll()

        val useCaseGroupBuilder = UseCaseGroup.Builder()

        if (isQRMode) {
            // 设置：QR码扫描模式
            val analyzer = QRAnalyzer(mActivity)
            val mIAnalyzer = ImageAnalysis.Builder().let {
                it.setTargetAspectRatio(aspectRatio)
//                .setTargetResolution(Size(1920, 1080))
                // 背压策略:只保留最新
                it.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    it.setOutputImageRotationEnabled(true)
                }
                it.build()
            }

            qrAnalyzer = analyzer
            imageAnalyzer = mIAnalyzer
            mIAnalyzer.setAnalyzer(cameraExecutor, analyzer)
            useCaseGroupBuilder.addUseCase(mIAnalyzer)
        } else {
            // 设置：拍照模式
            imageCapture = ImageCapture.Builder().let {
                // 拍照低延迟
                // todo优化：支持零延迟
                it.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
                // 设置目标旋转
                it.setTargetRotation(imageCapture?.targetRotation ?: rotation)
                // 设置拍照的图片分辨率（由相机拍照比例、系统支持的分辨率等参数决定）
                it.setTargetAspectRatio(aspectRatio)
                it.setFlashMode(ImageCapture.FLASH_MODE_AUTO)
                it.setJpegQuality(80)
                it.build()
            }

            useCaseGroupBuilder.addUseCase(imageCapture!!)
        }

        // 初始化Preview对象
        val previewBuilder = Preview.Builder()
            .setTargetRotation(
                preview?.targetRotation
                    ?: rotation
            )
//            .setTargetRotation(getRotation())
            .setTargetAspectRatio(aspectRatio)

        preview = previewBuilder.build().also {
            useCaseGroupBuilder.addUseCase(it)
            it.setSurfaceProvider(mActivity.previewView.surfaceProvider)
        }

        try {
            camera = cameraProvider!!.bindToLifecycle(
                mActivity, cameraSelector,
                useCaseGroupBuilder.build()
            )
        } catch (e: Throwable) {
            ErrorReporter.report(e)
            return
        }
    }

    /**切换相机模式*/
    fun switchMode(mode: CameraMode) {
        if (currentMode == mode) {
            return
        }

        currentMode = mode
        isQRMode = mode == CameraMode.QR_SCAN

        startCamera(true)
    }
}
